import glob
import os
import re
import shutil
import socket
import subprocess
import traceback as tb
import urllib2

from ezp_util import *

# ---------------------------------------------------------------------------
JAVA_BINARY = '/usr/local/java/bin/java'
THREDDS_ROOT = '/esg/content/thredds/esgcet'

# ---------------------------------------------------------------------------
def auth_read_thredds(url, username, password):
    """
    Perform an authenticated read on the THREDDS server at url as
    username/password.
    """
    log = simple_logger()
    tauth_realm = "THREDDS Data Server"
    auth_handler = urllib2.HTTPBasicAuthHandler()
    auth_handler.add_password(realm=tauth_realm,
                              uri=url,
                              user=username,
                              passwd=password)
    opener = urllib2.build_opener(auth_handler)

    urllib2.install_opener(opener)
    try:
        handle = urllib2.urlopen(url)
        page = handle.read()
        handle.close()
    except Exception, e:
        if "maximum recursion depth" in str(e):
            lograise("bad password for %s" % url)
        else:
            log.error(tb.format_exc())
            return
    return page

# ---------------------------------------------------------------------------
def get_dnode_password():
    rval = contents("/esg/config/.esgf_pass").strip()
    return rval

# ---------------------------------------------------------------------------
def solr_publish(xmllist, ingest=True):
    """
    Tickle the solr server to ingest or ungest THREDDS files.
    """
    log = simple_logger()
    log.debug("%s(ingest=%s)" % (my_name(), ingest))
    webinf = "/usr/local/tomcat/webapps/esg-search/WEB-INF"
    os.environ['CLASSPATH'] = '%s/classes' % webinf
    log.debug("%s: CLASSPATH = '%s'" % (my_name(), os.environ['CLASSPATH']))

    for fname in xmllist:
        cmd = [JAVA_BINARY,
               "-Djava.ext.dirs=%s/lib" % webinf,
               "-Dlog4j.configuration=%s/classes/log4j.xml" % webinf,
               "esg.search.publish.impl.PublishingServiceMain",
               "http://%s/thredds/esgcet/1/%s" % (socket.gethostname(),
                                                  os.path.basename(fname)),
               "THREDDS",
               str(ingest).lower()]

        log.debug("%s: cmd = '%s'" % (my_name(), " ".join(cmd)))
        proc = subprocess.Popen(cmd, 
                                stdout=subprocess.PIPE, 
                                stderr=subprocess.STDOUT)
        result = proc.stdout.readlines()
        for line in result:
            log.debug("%s: %s" % (my_name(), line.strip()))

        if has_java_exception("".join(result)):
            lograise("%s: solr publish failed: see %s for details"
                     % (my_name(), log.handlers[0].baseFilename))

# ---------------------------------------------------------------------------
def thredds_generate(app_prop_path):
    """
    Before calling this, the caller needs to write out an
    application.properties file, setting data.src to the directory
    contining the input files and catalog.root to the location where
    the THREDDS files and catalog.xml should be written.

    app_prop_path: where to find application.properties, which
                   specifies where the input files are (data.src) and
                   where the THREDDS files should go (${catalog.root}/1).

    Another option would be to pass in an input_path and catalog_path
    and put the code in here to actually write application.properties.
    """

    #
    # call scigest.core.CatalogGen
    #
    log = simple_logger()
    log.debug("%s(app_prop_path = %s)" % (my_name(), app_prop_path))
    build_path = "%s/build" % scigest_home()
    jar_path = "%s/lib" % scigest_home()
    resource_path = "%s/resources" % scigest_home()

    if 0 < len(glob.glob("%s/scigest-*.jar" % jar_path)):
        os.environ['CLASSPATH'] = "%s:%s" % (jar_path, resource_path)
        ext_dirs = jar_path
        print("adding %s, %s to class path" % (jar_path, resource_path))
    elif os.path.exists("%s/scigest/core/CatalogGen.class" % build_path):
        # os.environ['CLASSPATH'] = build_path
        os.environ['CLASSPATH'] = "%s:%s" % (build_path, resource_path)
        ext_dirs = "%s/lib/fetched/runtime" % scigest_home()
        # print("adding %s to class path" % build_path)
    else:
        lograise("Can't find CatalogGen at %s or %s" % (build_path, jar_path))

    log.debug("%s: CLASSPATH = '%s'" % (my_name(), os.environ['CLASSPATH']))
    cmd = '%s %s=%s %s=%s scigest.core.CatalogGen' \
          % (JAVA_BINARY,
             "-Dproperties.location",
             app_prop_path,
             "-Djava.ext.dirs",
             ext_dirs)
    log.debug("%s: cmd = '%s'" % (my_name(), cmd))
    proc = subprocess.Popen(cmd.split(" "),
                            stdout=subprocess.PIPE,
                            stderr=subprocess.STDOUT)
    result = proc.stdout.readlines()
    for line in result:
        log.debug("%s: %s" % (my_name(), line.rstrip()))

    if has_java_exception("".join(result)):
        lograise("%s: CatalogGen failed: see %s for details"
                 % (my_name(), log.handlers[0].baseFilename))
    else:
        flist = re.findall(r"Generating catalog file \[([^\]]+)\]", 
                           "".join(result))
        if 0 == len(flist):
            lograise("%s: CatalogGen failed: see %s for details"
                     % (my_name(), log.handlers[0].baseFilename))

    catlist = "%s/.scigest/catalog.txt" % user_home()
    f = open(catlist, 'w')
    for fpath in flist:
        # copy the .xml files into the THREDDS catalog
        base = os.path.basename(fpath)
        shutil.copy(fpath, "%s/1/%s" % (THREDDS_ROOT, base))
        f.write("%s\n" % (base))

    f.close()
    return catlist

# ---------------------------------------------------------------------------
def thredds_reinit():
    """
    Tickle the THREDDS server to reinit itself.
    """
    log = simple_logger()
    reinit_url = "https://localhost:443/thredds/admin/debug?catalogs/reinit"
    reinit_ok = "reinit ok"
    reinit_err_url = "https://localhost:443/thredds/admin" \
        + "/content/logs/catalogInit.log"
    reinit_err = "Catalog init"
    reinit_fatal = "**Fatal"
    tuser = "dnode_user"
    try:
        tpass = get_dnode_password()
    except:
        lograise("%s: db password not found for host %s"
                 % (my_name(), socket.gethostname()))
            
    result = ""
    try:
        result = auth_read_thredds(reinit_url, tuser, tpass)
    except Exception, e:
        msg = `e`
        if msg.find("maximum recursion depth") != -1:
            lograise("%s: bad password (%s)" % (my_name(), msg))
        else:
            lograise("%s: %s" % (my_name(), tb.format_exc()))
        
        if result.find(reinit_ok) == -1:
            lograise("%s: reinit THREDDS - '%s'" % (my_name(), result))

        result = auth_read_thredds(reinit_err_url, tuser, tpass)
        index = result.rfind(reinit_err)
        r2 = result[index:]
        findex = r2.find(reinit_fatal)
        if findex != -1:
            i2 = r2[findex:].find('\n')
            errmsg = r2[findex:findex+i2]
            lograise("%s: reinit THREDDS - '%s'\n%s" % (my_name(), errmsg, r2))

# ---------------------------------------------------------------------------
def thredds_xref(catlist, add=True):
    """
    The argument catlist may be a list of files or the name of a file 
    containing the list. If it is an in-memory list, we write it out to 
    a temporary file, use it, then remove the temp file. If it is the 
    name of a file, we use it and leave it alone.
    """
    log = simple_logger()
    log.debug("%s(%s, add=%s)" % (my_name(), catlist, add))

    filename = ''
    if type(catlist) == list:
        filename = "/tmp/ezpub_catlist.%d" % os.getpid()
        f = open(filename, 'w')
        for item in catlist:
            f.write("%s\n" % os.path.basename(item))
        f.close()
        catlist = filename

    os.environ['CLASSPATH'] = "%s/build:%s/resources" % (scigest_home(),
                                                         scigest_home())
    log.debug("%s: CLASSPATH = '%s'" % (my_name(), os.environ['CLASSPATH']))
    cmd = [JAVA_BINARY,
           "-Djava.ext.dirs=%s/lib/fetched/runtime" % scigest_home(),
           "scigest.core.CatalogXref",
           catlist,
           "file://%s/catalog.xml" % THREDDS_ROOT]
    if not add:
        cmd.append("remove")

    log.debug("%s: cmd = '%s'" % (my_name(), " ".join(cmd)))
    proc = subprocess.Popen(cmd, 
                            stdout=subprocess.PIPE, 
                            stderr=subprocess.STDOUT)
    result = proc.stdout.readlines()
    for line in result:
        log.debug(line.strip())

    if filename != '':
        os.unlink(filename)

    if has_java_exception("".join(result)):
        lograise("%s: CatalogGen failed: see %s for details" 
                 % (my_name(), log.handlers[0].baseFilename))


